package com.mycompany.inventory.viewmodel;

import java.util.ArrayList;
import java.util.List;

import org.zkoss.bind.BindUtils;
import org.zkoss.bind.annotation.BindingParam;
import org.zkoss.bind.annotation.NotifyChange;
import org.zkoss.bind.annotation.Command;
import org.zkoss.bind.annotation.Init;
import org.zkoss.zhtml.Messagebox;
import org.zkoss.zk.ui.Component;
import org.zkoss.zk.ui.event.Event;
import org.zkoss.zul.Bandbox;
import org.zkoss.zul.Window;
import org.zkoss.zul.Tab;

import com.mycompany.inventory.persistence.VendorDAO;
import com.mycompany.inventory.pojo.Address;
import com.mycompany.inventory.pojo.Carrier;
import com.mycompany.inventory.pojo.Currency;
import com.mycompany.inventory.pojo.CustomInfo;
import com.mycompany.inventory.pojo.PaymentTerm;
import com.mycompany.inventory.pojo.Product;
import com.mycompany.inventory.pojo.TaxScheme;
import com.mycompany.inventory.pojo.Vendor;
import com.mycompany.inventory.pojo.Contact;
import com.mycompany.inventory.pojo.VendorProduct;

import com.mycompany.inventory.persistence.CarrierDAO;
import com.mycompany.inventory.persistence.CurrencyDAO;
import com.mycompany.inventory.persistence.CustomFieldDAO;
import com.mycompany.inventory.persistence.PaymentTermDAO;
import com.mycompany.inventory.persistence.ProductDAO;
import com.mycompany.inventory.persistence.TaxSchemeDAO;
import com.mycompany.inventory.persistence.VendorProductDAO;

public class VendorViewModel implements org.zkoss.zk.ui.event.EventListener{
	private String name;
	private String remark;
	private boolean disableAddAddressFlag;

	private Vendor selectedVendor;
	private List<Vendor> vendors = new ArrayList();
	
	//payment term
	private PaymentTerm selectedPaymentTerm;
	private List<PaymentTerm> paymentTerms = new ArrayList();
	
	//tax schema
	private TaxScheme selectedTaxScheme;
	private List<TaxScheme> taxSchemes = new ArrayList();
	
	//carrier
	private Carrier selectedCarrier;
	private List<Carrier> carrier = new ArrayList();
	
	//currency
	private Currency selectedCurrency;
	private List<Currency> currencies = new ArrayList();

	// address window
	private Address selected;
	private List<Address> addresses = new ArrayList();
	private List types = new ArrayList();
	private List cities = new ArrayList();
	private List nation = new ArrayList();

	// CustomInfo
	private CustomInfo custom;
	private List<CustomInfo> customs = new ArrayList();

	// Contact
	private Contact contact = new Contact();
	
	//Product
	private Product selectedProduct;
	private List<Product> products = new ArrayList();
	
	private Product selectedVendorProduct;
	private List<Product> vendorProducts = new ArrayList();
	
	//dao
	private VendorDAO venDao = new VendorDAO();

	public Contact getContact() {
		return contact;
	}

	public void setContact(Contact contact) {
		this.contact = contact;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}
	
	public String getRemark() {
		return remark;
	}

	public void setRemark(String remark) {
		this.remark = remark;
	}

	// Address
	public List<Address> getAddressList() {
		return addresses;
	}

	public List getAddressTypes() {
		return types;
	}

	public List getAddressCities() {
		return cities;
	}

	public List getAddressNation() {
		return nation;
	}

	public void setSelectedAddress(Address selected) {
		this.selected = selected;
	}

	public Address getSelectedAddress() {
		return selected;
	}

	// Custom Info
	public List<CustomInfo> getCustomFieldList() {
		return customs;
	}

	public void setSelectedCustom(CustomInfo selected) {
		this.custom = selected;
	}

	public CustomInfo getSelectedCustom() {
		return custom;
	}

	// vendor list
	public Vendor getSelectedVendor() {
		return selectedVendor;
	}

	public void setSelectedVendor(Vendor selectedVendor) {
		this.selectedVendor = selectedVendor;
	}

	public List<Vendor> getVendorList() {
		return vendors;
	}

	public void setVendorList(List<Vendor> vendors) {
		this.vendors = vendors;
	}
	
	public PaymentTerm getSelectedPaymentTerm() {
		return selectedPaymentTerm;
	}

	public void setSelectedPaymentTerm(PaymentTerm selectedPaymentTerm) {
		this.selectedPaymentTerm = selectedPaymentTerm;
	}

	public List<PaymentTerm> getPaymentTerms() {
		return paymentTerms;
	}

	public void setPaymentTerms(List<PaymentTerm> paymentTerms) {
		this.paymentTerms = paymentTerms;
	}

	public TaxScheme getSelectedTaxScheme() {
		return selectedTaxScheme;
	}

	public void setSelectedTaxScheme(TaxScheme selectedTaxScheme) {
		this.selectedTaxScheme = selectedTaxScheme;
	}

	public List<TaxScheme> getTaxSchemes() {
		return taxSchemes;
	}

	public void setTaxSchemes(List<TaxScheme> taxSchemes) {
		this.taxSchemes = taxSchemes;
	}

	public Carrier getSelectedCarrier() {
		return selectedCarrier;
	}

	public void setSelectedCarrier(Carrier selectedCarrier) {
		this.selectedCarrier = selectedCarrier;
	}

	public List<Carrier> getCarrier() {
		return carrier;
	}

	public void setCarrier(List<Carrier> carrier) {
		this.carrier = carrier;
	}

	public Currency getSelectedCurrency() {
		return selectedCurrency;
	}

	public void setSelectedCurrency(Currency selectedCurrency) {
		this.selectedCurrency = selectedCurrency;
	}

	public List<Currency> getCurrencies() {
		return currencies;
	}

	public void setCurrencies(List<Currency> currencies) {
		this.currencies = currencies;
	}
	
	public boolean isDisableAddAddressFlag() {
		return disableAddAddressFlag;
	}

	public void setDisableAddAddressFlag(boolean disableAddAddressFlag) {
		this.disableAddAddressFlag = disableAddAddressFlag;
	}
	
	public Product getSelectedProduct() {
		return selectedProduct;
	}

	public void setSelectedProduct(Product selectedProduct) {
		this.selectedProduct = selectedProduct;
	}

	public List<Product> getProducts() {
		return products;
	}

	public void setProducts(List<Product> products) {
		this.products = products;
	}
	
	public Product getSelectedVendorProduct() {
		return selectedVendorProduct;
	}

	public void setSelectedVendorProduct(Product selectedVendorProduct) {
		this.selectedVendorProduct = selectedVendorProduct;
	}

	public List<Product> getVendorProducts() {
		return vendorProducts;
	}

	public void setVendorProducts(List<Product> vendorProducts) {
		this.vendorProducts = vendorProducts;
	}


	/**********************************************************************
	 *
	 *
	 *
	 *
	 *
	 *
	 *
	 ************************************************************************/
	
	@Init
	public void init() {
		updateVendorDetail();					
		updateVendorList();				
		
		disableAddAddressFlag = false;		
	}

	
	
	/**********************************************************************
	 *
	 *
	 * command function
	 *
	 *
	 *
	 *
	 ************************************************************************/
	
	
	//popup command
	@NotifyChange({"addresses", "disableAddAddressFlag"})
	@Command
	public void newAddress(@BindingParam("dlg") Window win) {
		// manipulate data		
		for (Address add : addresses){
			if(add.getAddress().equals("")){
				add.setId(selected.getId());
				add.setAddress(selected.getAddress());
				add.setCity(selected.getCity());
				add.setNational(selected.getNational());
				add.setRemark(selected.getRemark());
				add.setType(selected.getType());
				break;
			}
		}
		updateButtonStatus();
		win.onClose();
	}
	
	@NotifyChange("vendorProducts")
	@Command
	public void addProductToVendor(@BindingParam("para") Component comp, @BindingParam("productId")String productId) {
		// manipulate data		
		Component parent = comp.getParent();
		parent = parent.getParent();
		parent = parent.getParent();
		Bandbox box = (Bandbox)parent;
		updateVendorProduct(productId);
		box.close();		 	
	}
	
	@NotifyChange("customs")
	@Command
	public void updateCustomField(@BindingParam("dlg") Window win) {
		// manipulate data
		// addresses.add(new
		// Address(selected.getAddress(),selected.getCity(),selected.getNational(),selected.getRemark(),selected.getType()));
		//customs.add(new CustomInfo(custom.getName(), custom.getValue(),"","",true));
		win.onClose();
	}

	
	//vendor list command
	@NotifyChange({ "remark", "name", "contact", "addresses" , "customs" , "selectedPaymentTerm" , "selectedTaxScheme" , "selectedCarrier" , "selectedCurrency",  "disableAddAddressFlag" })
	@Command
	public void tabSelect() {
		if(selectedVendor == null){ 			
			return;		
		}		
		processEditVendor();
	}
	
	@NotifyChange({"vendorProducts" , "products"})
	@Command
	public void vendorProductTabSelect() {
		updateProduct();
	}
	
	@NotifyChange("vendors")
	@Command
	public void refreshList() {
		updateVendorList();
	}	
	
	@NotifyChange({ "remark" , "name", "contact", "addresses", "customs", "selectedPaymentTerm" , "selectedTaxScheme" , "selectedCarrier" , "selectedCurrency", "disableAddAddressFlag"})
	@Command
	public void editVendor(@BindingParam("para") Component tab) {
		Tab t = (Tab)tab;
		if(selectedVendor == null){
			Messagebox.show("No Vendor", "Information", Messagebox.OK, Messagebox.INFORMATION);
			return;
		}		
		processEditVendor();
		t.setSelected(true);
	}
	
	@NotifyChange({ "name", "contact", "addresses" , "customs" , "selectedPaymentTerm" , "selectedTaxScheme" , "selectedCarrier" , "selectedCurrency", "disableAddAddressFlag" })
	@Command
	public void createVendor(@BindingParam("para") Component tab) {		
		Tab t = (Tab)tab;
		name = "";
		remark = "";
		contact.clear();	
		for (Address add : addresses){
			add.clear();
		}
		for (CustomInfo cus : customs){
			cus.clear();
		}
		selectedPaymentTerm = null;
		selectedTaxScheme = null;
		selectedCarrier = null;
		selectedCurrency = null;		
		selectedVendor = null;
		disableAddAddressFlag = false;
		
		t.setSelected(true);
	}
	
	@NotifyChange("vendors")
	@Command
	public void deleteVendor() {	
		if(selectedVendor == null){ 
			Messagebox.show("No Vendor", "Information", Messagebox.OK, Messagebox.INFORMATION);
			return;		
		}		
		//Messagebox.show("Are you sure to delete?", "Confirm Dialog", Messagebox.OK | Messagebox.CANCEL, Messagebox.QUESTION, this); 
		
		venDao.delete(selectedVendor);	
    	updateVendorList();  
	}
		
	public void onEvent(Event evt) throws InterruptedException {
        if (evt.getName().equals("onOK")) {
        	venDao.delete(selectedVendor);	
        	updateVendorList();  
        	BindUtils.postNotifyChange(null,null,this,"vendors");
        } else {	
        	return;
        }
    }
	
	//vendor detail command	
	@NotifyChange("vendors")
	@Command("save")
	public void newVendor(@BindingParam("para") Component tab) {	
		Vendor vendor;
		if(selectedVendor == null){
			vendor = new Vendor("3",name, 0, addresses,contact,customs,remark,selectedPaymentTerm,selectedTaxScheme,selectedCarrier,selectedCurrency);		
			venDao.create(vendor);
		}else{
			vendor = new Vendor(selectedVendor.getId(),name, 0, addresses,contact,customs,remark,selectedPaymentTerm,selectedTaxScheme,selectedCarrier,selectedCurrency);
			venDao.update(vendor);
		}
		updateVendorList();
		Tab t = (Tab)tab;
		t.setSelected(true);
	}	
	
	@NotifyChange("vendorProducts")
	@Command
	public void addToVendor() {	
		VendorProductDAO dao = new VendorProductDAO();
		for(Product pro : vendorProducts){
			if(!pro.getId().equals("")){
				if(dao.find(Long.parseLong(pro.getId()))!= null){
					if(pro.isDeleted()){
						dao.delete(new VendorProduct("", selectedVendor.getId(), pro.getId()));
					}
				}else{
					dao.create(new VendorProduct("", selectedVendor.getId(), pro.getId()));
				}	
			}
		}
		
		ProductDAO proDao = new ProductDAO();
		vendorProducts = proDao.findByVendorID(Long.parseLong(selectedVendor.getId()));
		vendorProducts.add(new Product("", "", "", "", "", ""));
	}	
	
	
	

	/**********************************************************************
	 *
	 *
	 * Util function
	 *
	 *
	 *
	 *
	 ************************************************************************/
	
	private void updateButtonStatus(){
		if(addresses.get(3).getAddress().equals("")){
			 disableAddAddressFlag = false;
		}else{
			disableAddAddressFlag = true;
		}
	}
	
	private void processEditVendor(){
		name = selectedVendor.getName();
		remark = selectedVendor.getRemark();
		if(selectedVendor.getContact()!= null)
			contact.copyValue(selectedVendor.getContact());
		
		for (int i = 0 ; i < 4 ;i++){
			if(i < selectedVendor.getAddresses().size() ){
				addresses.get(i).copyValue(selectedVendor.getAddresses().get(i));
			}else{
				addresses.get(i).clear();
			}						
		}		
		
		updateButtonStatus();
		
		
		for (int i = 0 ; i < customs.size() ;i++){
			customs.get(i).copyValue(selectedVendor.getCustoms().get(i));
		}
		
		if(paymentTerms!= null && selectedVendor.getPaymentTerm() != null)
			for (int i = 0 ; i < paymentTerms.size() ;i++){
				if(paymentTerms.get(i).getName().equals(selectedVendor.getPaymentTerm().getName())){
					selectedPaymentTerm = paymentTerms.get(i);
					break;
				}
			}
		
		if(taxSchemes!= null && selectedVendor.getTaxingScheme() != null)
			for (int i = 0 ; i < taxSchemes.size() ;i++){
				if(taxSchemes.get(i).getName().equals(selectedVendor.getTaxingScheme().getName())){
					selectedTaxScheme = taxSchemes.get(i);
					break;
				}
			}
		
		if(carrier!= null && selectedVendor.getCarrier() != null)
			for (int i = 0 ; i < carrier.size() ;i++){
				if(carrier.get(i).getName().equals(selectedVendor.getCarrier().getName())){
					selectedCarrier = carrier.get(i);
					break;
				}
			}
		
		if(currencies!= null && selectedVendor.getCurrency() != null)
			for (int i = 0 ; i < currencies.size() ;i++){
				if(currencies.get(i).getName().equals(selectedVendor.getCurrency().getName())){
					selectedCurrency = currencies.get(i);
					break;
				}
			}
				
	}	
	
	/*
	 * update function
	 */
		
	private void updateVendorList(){
		// init vendor list	
		vendors = venDao.findAll();
		selectedVendor = (vendors == null || vendors.size() == 0)  ? null : vendors.get(0);
	}
	
	private void updateVendorDetail(){
				
		updateAddress();
		
		updateCustomField();
		
		updatePaymentTerm();
		
		updateTaxScheme();
		
		updateCarrier();
		
		updateCurrency();				
				
	}
	
	private void updateVendorProduct(String id){
		for(Product pro : vendorProducts){
			if(pro.getId().equals(id)){
				pro.copyValue(selectedProduct);
				break;
			}
		}
		if(!vendorProducts.get(vendorProducts.size() - 1).getId().equals(""))
			vendorProducts.add(new Product("", "", "", "", "", ""));
	}
	
	
	private void updateProduct(){
		ProductDAO dao = new ProductDAO();
		products = dao.findAll();
		//selectedProduct = products.get(0);
		
			
		vendorProducts = dao.findByVendorID(Long.parseLong(selectedVendor.getId()));
		vendorProducts.add(new Product("", "", "", "", "", ""));
		
		//selectedVendorProduct = null;
	}
	
	private void updateAddress(){
		addresses.add(new Address("", "", "", "", "", ""));
		addresses.add(new Address("", "", "", "", "", ""));
		addresses.add(new Address("", "", "", "", "", ""));
		addresses.add(new Address("", "", "", "", "", ""));
		selected = new Address();
		
		//init address popup
		types.add("Commercial");
		types.add("Residential");

		cities.add("Ho Chi Minh");
		cities.add("Da nang");

		nation.add("Viet Nam");
		nation.add("Lao");

	}
	
	private void updateCustomField(){
		// init custom field
		CustomFieldDAO dao = new CustomFieldDAO();
		customs = dao.findAll("Vendor");
		custom = new CustomInfo();
	}
	
	private void updatePaymentTerm(){
		//init payment term
		PaymentTermDAO dao = new PaymentTermDAO();
		paymentTerms = dao.findAll();
		selectedPaymentTerm = new PaymentTerm("", "", "", 0);
	}
	
	private void updateTaxScheme(){
		//init tax Schemes
		TaxSchemeDAO dao = new TaxSchemeDAO();
		taxSchemes = dao.findAll();
		selectedTaxScheme = new TaxScheme("", "", "", "", 0);
	}
	
	private void updateCarrier(){
		//init carrier
		CarrierDAO dao = new CarrierDAO();
		carrier = dao.findAll();
		selectedCarrier = new Carrier("", "", "");
	}
	
	private void updateCurrency(){
		//init currency
		CurrencyDAO dao = new CurrencyDAO();
		currencies = dao.findAll();
		selectedCurrency = new Currency("", "", "");
	}
	
}